#pragma once
#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<queue>
#include<math.h>
#include<map>
#include<string>
#include<string.h>
#include<sys/socket.h>


#define MAX_THREAD 5
class Task{
private:
    int sock;
    std::map<std::string,std::string> dict;
public:
    Task(int _sock):sock(_sock)
    {
        dict.insert(std::pair<std::string,std::string>("apple","苹果"));
        dict.insert(std::pair<std::string,std::string>("banana","香蕉"));
        dict.insert(std::pair<std::string,std::string>("car","汽车"));
        dict.insert(std::pair<std::string,std::string>("sun","☀"));
        dict.insert(std::pair<std::string,std::string>("moon","🌙"));
        dict.insert(std::pair<std::string,std::string>("star","⭐"));
    }
    void run(){
            char buffer[128];
            ssize_t s = recv(sock,buffer,sizeof(buffer)-1,0);
            if(s > 0){
                std::string echo = "unknow";
                auto it = dict.find(buffer);
                if(it != dict.end()){
                    echo = dict[buffer];
                }
                send(sock,echo.c_str(),echo.size(),0);
            }
            else if(s == 0){
                std::cout<<"Client quit ..."<<std::endl;
            }
            else{
                std::cout<<"recv error"<<std::endl;
            }
    }
    ~Task(){
        std::cout<<"close sock:"<<sock<<std::endl;
        close(sock);
    }
};

class ThreadPool{
private:
    std::queue<Task*> _q;
    int max_thread;
    pthread_mutex_t lock;
    pthread_cond_t cond;
public:
    ThreadPool(int max= MAX_THREAD):max_thread(max)
    {}

    static void* Routine(void* arg){
        //线程分离
        pthread_detach(pthread_self());
        ThreadPool* p_this = (ThreadPool*)arg;
        while(true){
            //保证生产者之间的互斥关系
            p_this->LockQueue();
            //当前任务队列没有任务就陷入阻塞等待生产者的唤醒
            while(p_this->IsEmpty()){
                p_this->ThreadWait();
            }//从任务队列中拿数据
            Task* t;
            p_this->Get(&t);
            p_this->UnlockQueue();
            //处理任务
            t->run();
            delete t;
        }
    }
    void ThreadInit(){
        pthread_mutex_init(&lock,nullptr);
        pthread_cond_init(&cond,nullptr);
        pthread_t tid;
        for(int i=0;i<max_thread;++i){
            pthread_create(&tid,nullptr,Routine,this);
        }
    }
    //往任务队列中放数据(主线程调用)
    void Put(Task& in){
        //保证生产者之间的互斥关系
        LockQueue();
        _q.push(&in);
        UnlockQueue();
        //放入数据就唤醒一个消费者处理任务
        ThreadWakeUp();
    }

    //从任务队列中拿数据(线程池中的线程调用)
    void Get(Task** out){
        Task* t = _q.front();
        _q.pop();
        *out = t;
    }
public:
    void LockQueue(){
        pthread_mutex_lock(&lock);
    }
    void UnlockQueue(){
        pthread_mutex_unlock(&lock);
    }
    void ThreadWait(){
        pthread_cond_wait(&cond,&lock);
    }
    void ThreadWakeUp(){
        pthread_cond_signal(&cond);
    }
    bool IsEmpty(){
        return _q.size()==0;
    }
    ~ThreadPool(){
        pthread_mutex_destroy(&lock);
        pthread_cond_destroy(&cond);
    }
};
